/*
	Adobe Systems Incorporated(r) Source Code License Agreement
	Copyright(c) 2007 Adobe Systems Incorporated. All rights reserved.
	
	Please read this Source Code License Agreement carefully before using
	the source code.
	
	Adobe Systems Incorporated grants to you a perpetual, worldwide, non-exclusive, 
	no-charge, royalty-free, irrevocable copyright license, to reproduce,
	prepare derivative works of, publicly display, publicly perform, and
	distribute this source code and such derivative works in source or 
	object code form without any attribution requirements.  
	
	The name "Adobe Systems Incorporated" must not be used to endorse or promote products
	derived from the source code without prior written permission.
	
	You agree to indemnify, hold harmless and defend Adobe Systems Incorporated from and
	against any loss, damage, claims or lawsuits, including attorney's 
	fees that arise or result from your use or distribution of the source 
	code.
	
	THIS SOURCE CODE IS PROVIDED "AS IS" AND "WITH ALL FAULTS", WITHOUT 
	ANY TECHNICAL SUPPORT OR ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
	FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ALSO, THERE IS NO WARRANTY OF 
	NON-INFRINGEMENT, TITLE OR QUIET ENJOYMENT.  IN NO EVENT SHALL ADOBE
	OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
	OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
	OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOURCE CODE, EVEN IF
	ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.adobe.apps.ascension
{
	import mx.rpc.http.HTTPService;
	import mx.utils.StringUtil;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.events.FaultEvent;
	import com.adobe.apps.ascension.utils.URLCache;
	import com.adobe.apps.ascension.events.URLCacheEvent;
	import flash.filesystem.File;
	import com.adobe.apps.ascension.SongMetaDataPopulator;
	import com.adobe.apps.ascension.utils.AscensionCacheEnum;
	import com.adobe.apps.ascension.events.APIKeyErrorEvent;
	import flash.events.EventDispatcher;

	
	//todo: check this for memory leaks
	public class SongMetaDataPopulator extends EventDispatcher
	{
		private const RELATED_INFO_BASE_URL:String = "http://xml.musicmobs.com/services/music/{0}/";
		private const SONG_INFO_BASE_URL:String = "http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId={0}&Operation=ItemSearch&Keywords={1}&SearchIndex=Music";
		private const SONG_IMAGE_BASE_URL:String = "http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId={0}&Operation=ItemLookup&ItemId={1}&ResponseGroup=Images";
		private var _amazonKey:String;
		
		private var ans:Namespace = new Namespace("http://webservices.amazon.com/AWSECommerceService/2005-10-05");
		
		private var _song:Song;
		
		private var key:String;
		
		public function SongMetaDataPopulator(song:Song, amazonKey:String)
		{
			_song = song;
			_amazonKey = getApiKey(amazonKey);
			
			key = _song.artist + _song.album;
					
		}
		
		private function getApiKey(l:String):String
		{
			var key:String = l;
			
			if(key != null && key.length != 0)
			{
				return key;
			}
			
			//this is a token replace by ANT builds do not modify
			var hKey:String = null/*#AMAZON_API_KEY*/;
			
			return hKey;
		}		
		
		public function loadMetaData():void
		{
			//check if the user has set the API key, if they have not dispatch an
			//event, and then dont try and load the meta data.
			if(_amazonKey == null)
			{
				var e:APIKeyErrorEvent = new APIKeyErrorEvent(APIKeyErrorEvent.AMAZON_API_KEY_NOT_SET);
				dispatchEvent(e);
				return;
			}

			var cache:URLCache = new URLCache(AscensionCacheEnum.ALBUM_ART);
			
			if(cache.itemExists(key))
			{
				var fl:File = cache.getItemFile(key);
				
				_song.albumArtPath = getFileURL(fl);
			}			
			
			
			if(_song.albumArtPath == null)
			{
				loadAmazonMetaData();
			}
			
			
			//todo : check this logic
			if(_song.relatedArtists == null)
			{
				loadRelatedInfo();
			}
		}
		
		private function loadASINInfo(asin:String):void
		{
			if(asin == null)
			{
				return;
			}
			
			var service:HTTPService = new HTTPService();
				service.url = StringUtil.substitute(SONG_IMAGE_BASE_URL, _amazonKey, asin);
				service.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
				service.addEventListener(ResultEvent.RESULT, onASINResult);
				service.addEventListener(FaultEvent.FAULT, onFault);
				
				service.send();
		}
		
		private function loadAmazonMetaData():void
		{
			var service:HTTPService = new HTTPService();
				service.url = StringUtil.substitute(SONG_INFO_BASE_URL, _amazonKey, escape(_song.artist + " " + _song.album));
				service.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
				service.addEventListener(ResultEvent.RESULT, onAmazonIDResult);
				service.addEventListener(FaultEvent.FAULT, onFault);
				
				service.send();
		}
		
		private function loadRelatedInfo():void
		{			
			//todo: check and see if meta data has already been populated.
			var service:HTTPService = new HTTPService();
			service.url = StringUtil.substitute(RELATED_INFO_BASE_URL, escape(_song.artist));
			service.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
			service.addEventListener(ResultEvent.RESULT, onRelatedResult);
			service.addEventListener(FaultEvent.FAULT, onFault);
			
			service.send();			
		}
		
		private function onRelatedResult(event:ResultEvent):void
		{			
			var xml:XML = new XML(event.result);			
			var xList:XMLList = xml.Related.Artist..@["name"];
			
			var arr:Array = new Array();
			
			for each(var r:String in xList)
			{
				arr.push(r);
			}
			
			_song.relatedArtists = arr;
			//_song.metaDataPopulated = true;
		}		
		
		private function onAmazonIDResult(event:ResultEvent):void
		{
			var xml:XML = new XML(event.result);
			
			var itemsList:XMLList = xml.ans::Items.ans::Item;
			
			if(itemsList.length() == 0)
			{
				trace("Amazon : Artist / Album Not Found");
				return;
			}
			
			var asin:String = itemsList[0].ans::ASIN;
			loadASINInfo(asin);
			
		}
		
		private function onASINResult(event:ResultEvent):void
		{
			var xml:XML = new XML(event.result);
			var items:XMLList = xml.ans::Items.ans::Item;
			
			if(items.length() < 1)
			{
				trace("ASIN : No Items Found");
				return;
			}
			
			var item:XML = items[0];
			
			var cache:URLCache = new URLCache(AscensionCacheEnum.ALBUM_ART);
				cache.addEventListener(URLCacheEvent.ITEM_READY, onItemReady);
			
				var l:String = item.ans::LargeImage.ans::URL;
				var m:String = item.ans::MediumImage.ans::URL;
				var s:String = item.ans::SmallImage.ans::URL;
				var p:String;
				
				//figure out the larges image size avaliable
				if(l != null && l.length > 0)
				{
					p = l;
				}
				else if(m != null && m.length > 0)
				{
					p = m;
				}
				else if(s != null && s.length > 0)
				{
					p = s;
				}
			
				cache.cacheURL(p, key);
		}
		
		private function onItemReady(event:URLCacheEvent):void
		{
			_song.albumArtPath = getFileURL(event.file);
		}
		
		private function onFault(fault:FaultEvent):void
		{
			trace("Error Loading Artist Meta Data : " + fault.message);
		}
		
		//hack to get file:// url
		private function getFileURL(f:File):String
		{
			return (new File(f.nativePath)).url;
		}
	}
}